﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SQLite;
using System.Linq;
using System.Text;
using BlobNet.Base.DataProviders;
using BlobNet.DefaultDataProviders.Base;

namespace BlobNet.DefaultDataProviders.SqlLite
{
    [Serializable]
    public class KVSDataProvider : KVSDataProviderBase, IDataProvider
    {
        private const int SQL_SERVER_MAX_SIZE = -1;

        private static readonly string[] ScriptKeywords = new[]
                                                               {
                                                                   "{DATABASE_NAME}", 
                                                                   "{CONTEXT_PREFIX}",
                                                                   "{SIZE_PROPERTIES}"
                                                               };

        private string _connStr;

        protected override string ConnectionString
        {
            get
            {
                if (string.IsNullOrEmpty(_connStr))
                    _connStr =
                        ConfigurationManager.AppSettings["BlobNet.DefaultProviders.KVSSqlLite.ConnectionString"];
                return _connStr;
            }
        }

        protected override int BinaryFieldMaxSize
        {
            get { return SQL_SERVER_MAX_SIZE; }
        }

        protected override void ClearResources()
        {
            SQLiteConnection.ClearAllPools();
        }

        protected override IDbConnection NewConnection()
        {
            var sqLiteConnection = new SQLiteConnection(ConnectionString);
            return sqLiteConnection;
        }

        protected override void AddParameter(object value, IDbCommand command, string paramName, DbType fieldType,
                                             ParameterDirection parameterDirection)
        {
            AddParameter(value, command, paramName, fieldType, parameterDirection, 0);
        }

        protected override void AddParameter(object value, IDbCommand command, string paramName, DbType fieldType,
                                             ParameterDirection parameterDirection, int size)
        {
            var parameter = new SQLiteParameter(paramName, value ?? DBNull.Value) { DbType = fieldType, Direction = parameterDirection, Size = size };

            ((SQLiteCommand)command).Parameters.Add(parameter);
        }

        //TODO: dependency injection for this reader

        #region Nested type: ConnectionStringHandler
        private static class ConnectionStringHandler
        {
            private static readonly Dictionary<string, string> connectionDict = new Dictionary<string, string>();

            static ConnectionStringHandler()
            {
                string connString =
                    ConfigurationManager.AppSettings["BlobNet.DefaultProviders.KVSSqlServer2008.ConnectionString"];

                string[] tmp = connString.Split(';');

                foreach (string s in tmp)
                {
                    string[] strings = s.Split('=');
                    connectionDict.Add(strings[0].ToLower(), strings[1]);
                }
            }

            public static string CurrentCatalog
            {
                get { return connectionDict["initial catalog"]; }
            }
        }
        #endregion

        protected override string CreateStorageScriptName
        {
            get { return "BlobNet.DefaultDataProviders.SqlLite.Scripts.CreateStorage.sql"; }
        }

        protected override string RemoveStorageScriptName
        {
            get { return "BlobNet.DefaultDataProviders.SqlLite.Scripts.RemoveStorage.sql"; }
        }

        protected override string ReplaceScriptKeywords(Guid blobDomainId, string scriptString)
        {
            string result = scriptString;
            string appSetting = ConnectionStringHandler.CurrentCatalog;
            string blobDomainPrefix = GetBlobDomainPrefix(blobDomainId);
            foreach (string scriptKeyword in KVSDataProvider.ScriptKeywords)
            {
                switch (scriptKeyword)
                {
                    case "{DATABASE_NAME}":
                        result = result.Replace(scriptKeyword, appSetting);
                        break;
                    case "{CONTEXT_PREFIX}":
                        result = result.Replace(scriptKeyword, blobDomainPrefix);
                        break;
                    case "{SIZE_PROPERTIES}":
                        result = result.Replace(scriptKeyword,
                                                ConfigurationManager.AppSettings["BlobPropertyNamesMaxLength"]);
                        break;
                    default:
                        throw new NotImplementedException(scriptKeyword);
                }
            }
            return result;
        }
    }
}
